using System;
using System.Collections;
using System.Collections.Specialized;
using System.Xml.XPath;


namespace Actions.Databases
{
	/// <summary>
	/// QueryResult - store result of query in single associative array.
	/// </summary>
	public class QueryResult
	{
		private static int			_maxIterations = 100;			
		
		private Transaction 		_source;
		private ArrayList 			_results;		

        public delegate string      TreeIterCallback(string id);
        public delegate string      ContentModificator(string id);

		public ArrayList			res
		{
			get
			{
				return	_results;
			}
		}	
		
		public QueryResult(string q)
		{
			_source = new Transaction(q);
			_results = new ArrayList();
		}

		public QueryResult(Transaction t)
		{
			_source = t;
			_results = new ArrayList();			
		}
		
		//
		// Initialization
		//
		public void Add(NameValueCollection a)
		{
			_results.Add(a);
		}

		public string got(int i, string s)
		{
			return (_results[i] as NameValueCollection)[s];
		}

        public void appendTo(int i, string k, string v)
        {
           (_results[i] as NameValueCollection)[k] = v;
        }
        
        public void appendTo(string sk, string sv, string k, string v)
        {
           foreach(NameValueCollection r  in _results) {
              if(r[sk] == sv) r[k] = v;
           }
        }
    
        public bool inResults(string k, string v)
        {
           bool res = false;
           
           foreach(NameValueCollection r  in _results) {
              if(r[k] == v) {
                 res = true;
                 break;
              }
           }
           return res;
        }
        
		//
		// Serialize operations
		//
		public string serializeAsList(string bid, string iid)
		{
			string res = "";
			
			if(_results.Count > 0) {
				res += "<" + bid + ">\n";
				foreach(NameValueCollection r in _results) {
					res += "\t<" + iid + ">\n";
					foreach(string k in r.Keys) {
						res += "\t\t<" + k + ">" + r.Get(k) + "</" + k + ">\n";
					}
					res += "\t</" + iid + ">\n";
				}				
				res += "</" + bid + ">\n";
			}
			
			return res;			
		}
		
		public string serializeAsList(string bid, string iid, ContentModificator tic)
		{
			string res = "";
			
			if(_results.Count > 0) {
				res += "<" + bid + ">\n";
				foreach(NameValueCollection r in _results) {
					res += "\t<" + iid + ">\n";
					foreach(string k in r.Keys) {
						res += "\t\t<" + k + ">" + tic(r.Get(k)) + "</" + k + ">\n";
					}
					res += "\t</" + iid + ">\n";
				}				
				res += "</" + bid + ">\n";
			}
			
			return res;			
		}
		
		public string serializeAsTree(string bid, string iid, string sid, 
		                              string id, string pid, TreeIterCallback tic)
		{
			string res = "";
			
			if(_results.Count > 0) {
				res += "<" + bid + ">\n";
				res += serializeAsTreeIter("0", 1, iid, sid, id, pid, tic);
				res += "</" + bid + ">\n";
			}			
			
			return res;			
		}
		
		protected string serializeAsTreeIter(string parent, int k, 
		                                     string iid, string sid,
		                              		 string id, string pid,
		                              		 TreeIterCallback tic)
		{
			string res = "";
			
			if(k > _maxIterations) return res;
			
			foreach(NameValueCollection r in _results) {
				if(r[pid] == parent) {
					res += "\t<" + iid + " level='" + k + "'>\n";
					foreach(string ks in r.Keys) {
						res += "\t\t<" + ks + ">" + r.Get(ks) + "</" + ks + ">\n";
					}
					
					res += tic(r[id]);
					
					string sub = "";
					sub = serializeAsTreeIter(r[id], k + 1, iid, sid, id, pid, tic);
					if(sub.Length > 1) {
						res += "\t\t<" + sid + ">\n" + sub + "\t\t</" + sid + ">\n";
					}
					
					res += "\t</" + iid + ">\n";
				}
			}	
			return res;
		}
		
		public static string Pager(int total, int begin, int npp, int ppp, string url)
		{
			string s = "";
			int npages, cpage, bp, ep, b, e;
			
			if(total <= 0 || npp <= 0 || ppp <= 0) return s;
			
			if((total % npp) > 0) npages = (int) Math.Floor((double) total / npp) + 1;
			else npages = (int) Math.Floor((double) total / npp);
			
    		begin++;
			cpage = (begin - (begin % npp)) / npp;   
	    		
    		bp = cpage - ppp / 2 + 1;
    		ep = cpage + ppp / 2;	
	    	if(bp < 1) { ep = ep + (1 - bp); bp = 1; }; 
		    if(ep > npages) { bp = bp - (ep - npages); ep = npages; };
	    	if(bp < 1 || ep > npages || bp > ep) { bp = 1; ep = npages; }; 
    
	    	s += "\n<pages total='" + npages +"' records='" + total + "'>\n";
	   		if(bp > 1) {
				b = (bp - 2) * npp + 1;
				e = (bp - 1) * npp;	
 	 	        string iurl = String.Format(url, (b - 1));
				s += "\t<ppage begin='" + b + "' end='" + e + "' URL='" + iurl + "' />\n";
	    	};
    
	    	for(int i = bp; i < (ep + 1); i++) {
				b = (i - 1) * npp + 1;
				e = i * npp;
				if(begin >= b && begin <= e) {
					s += "\t<cpage begin='" + b + "' end='" + e + "'>" + i + "</cpage>\n";
				} else {
	 	 	        string iurl = String.Format(url, (b - 1));;
					s += "\t<tpage begin='" + b + "' end='" + e + "' URL='" + iurl + "'>" + i + "</tpage>\n";
				};
	    	};

	    	if(ep < npages) {
				b = ep * npp + 1;
				e = (ep + 1) * npp;	
 	 	        string iurl = String.Format(url, (b - 1));;
				s += "\t<npage begin='" + b + "' end='" + e + "' URL='" + iurl + "' />\n";
	    		};
			s += "</pages>\n";			

			return s;
		}
	}
}
